#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

class EventListeners
{
public:
    virtual void update(std::string filename) = 0;
};

class EmailAlertsListener :public EventListeners
{
    void update(std::string filename)
    {
        std::cout<<"Email: "<<filename <<" event."<<std::endl;
    }
};

class LoggingListener :public EventListeners
{
    void update(std::string filename)
    {
        std::cout<<"Logging: "<<filename <<" event."<<std::endl;
    }
};
enum class EventType
{
    OPEN,
    SAVE
};
class EventManager
{
private:
    std::vector<EventListeners*> listeners;
    std::vector<EventType> listenersType;
    std::vector<bool> listenersEnable;
public:
    void subscribe(EventType eventType, EventListeners* listener)
    {
        listeners.push_back(listener);
        listenersType.push_back(eventType);
        listenersEnable.push_back(true);
    }
    void unsubscribe(EventType eventType, EventListeners* listener)
    {
        auto pos = find(listeners.begin(), listeners.end(), listener);
        int idx = pos - listeners.begin();
        if(idx < listeners.size())
        {
            listenersEnable[idx] = false;
        }
    }
    void notify(EventType eventType, std::string data)
    {
        for(int i = 0; i < listeners.size(); ++i)
        {
            if(listenersEnable[i] && listenersType[i] == eventType)
            {
                listeners[i]->update(data);
            }
        }
    }
};

class Editor
{
private:
    EventManager eventManager;
public:
    Editor()
    {
        eventManager.subscribe(EventType::SAVE, new EmailAlertsListener());
        eventManager.subscribe(EventType::OPEN, new EmailAlertsListener());
        eventManager.subscribe(EventType::SAVE, new LoggingListener());
    }
    void openFile(std::string filename)
    {
        eventManager.notify(EventType::OPEN, filename);
    }
    void saveFile(std::string filename)
    {
        eventManager.notify(EventType::SAVE, filename);
    }
};
int main() {
    Editor editor;
    editor.openFile("test.txt");
    editor.saveFile("test.md");
    return 0;
}

